package cn.zxf.note.note.type;

import cn.zxf.note.common.exception.BizException;
import cn.zxf.note.note.note.NoteSupport;
import cn.zxf.note.note.type.dto.NoteTypeDto;
import cn.zxf.note.note.type.dto.NoteTypeStatisticsDto;
import cn.zxf.note.security.UserAuthService;
import com.github.zengxf.common.utils.BeanUtils;
import com.github.zengxf.common.utils.ListUtils;
import cn.hutool.core.collection.CollUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

@Component
public class NoteTypeService implements NoteTypeConstant {

    @Autowired
    private NoteTypeRepository repos;
    @Autowired
    private NoteTypeDao dao;
    @Autowired
    private NoteTypeSupport support;
    @Autowired
    private NoteSupport noteSupport;
    @Autowired
    private UserAuthService authService;

    public List<NoteTypeDto> findAll(Integer userId) {
        authService.validate(userId);
        List<NoteType> list = repos.findByUserId(userId);
        if (CollUtil.isEmpty(list))
            list.add(this.getAndSaveDef(userId));
        return ListUtils.simpleTransformList(list, NoteTypeDto::new);
    }

    public List<NoteTypeStatisticsDto> statistics(Integer userId) {
        authService.validate(userId);
        List<NoteTypeStatisticsDto> list = dao.statistics(userId);
        if (CollUtil.isEmpty(list)) {
            NoteType def = this.getAndSaveDef(userId);
            NoteTypeStatisticsDto dto = BeanUtils.transform(def, NoteTypeStatisticsDto::new);
            dto.setNoteNumber(0);
            list.add(dto);
        }
        return list;
    }

    public NoteTypeDto save(Integer userId, NoteTypeDto dto) {
        NoteType type = Optional.ofNullable(dto.getId())
                .flatMap(repos::findById)
                .orElseGet(NoteType::new);
        boolean insert = type.getId() == null;
        {
            authService.validate(userId, type.getUserId());
            String name = dto.getName();
            NoteType temp = dao.findByName(userId, name);
            if (temp != null && !Objects.equals(temp.getId(), type.getId()))
                throw BizException.of("类型【%s】已存在", name);
        }
        BeanUtils.copyProperties(dto, type);
        if (insert)
            type.setStatus(NoteTypeStatusEnum.NORMAL.code);
        type.setUserId(userId);
        repos.save(type);
        return BeanUtils.transform(type, NoteTypeDto::new);
    }

    public NoteTypeDto delete(Integer userId, Integer typeId) {
        NoteType type = support.validateAndGet(typeId);
        authService.validate(userId, type.getUserId());
        int count = noteSupport.countByTypeId(typeId);
        if (count > 0)
            throw BizException.of("当前类型下还有笔记，不能删除");
        type.setStatus(NoteTypeStatusEnum.DELETED.code);
        repos.save(type);
        return BeanUtils.transform(type, NoteTypeDto::new);
    }

    private NoteType getAndSaveDef(Integer userId) {
        NoteType type = new NoteType().setUserId(userId)
                .setName(DEF_NAME)
                .setStatus(NoteTypeStatusEnum.NORMAL.code);
        repos.save(type);
        return type;
    }

}
